#ifndef abb_H
#define abb_H

#include <stddef.h> /* size_t */
#include <stdbool.h> /* bool */

/*****************************************************************
 *        	DEFINICION DE LOS TIPOS DE DATOS Y FUNCIONES
 *****************************************************************/

typedef struct abb abb_t;

typedef int (*abb_comparar_clave_t) (const char *, const char *);
typedef void (*abb_destruir_dato_t) (void *);

typedef struct abb_iter abb_iter_t;

/* *****************************************************************
 *                    PRIMITIVAS DEL ARBOL
 * *****************************************************************/
//post: devuelve un abb vacio o NULL si no pudo completar la operacion.
abb_t* abb_crear(abb_comparar_clave_t cmp, abb_destruir_dato_t destruir_dato);

//post: devuelve true si guardo el dato asociado a la clave en el abb.
//false si el abb o la clave no existen, o si hubo un error en la operacion.
bool abb_guardar(abb_t *abb, const char *clave, void *dato);

//post: devuelve el dato asociado a la clave, el mismo fue borrado el abb,
//devuelve NULL si el abb o la clave no existen, si el abb esta vacio o si la
//clave no esta asociado a ningun dato dentro del abb.
void *abb_borrar(abb_t *abb, const char *clave);

//post: devuelve el dato asociado a la clave.
//Devuelve NULL si el abb esta vacio o si no existe dato asociado a la clave.
void *abb_obtener(const abb_t *abb, const char *clave);

//post: devuelve true si existe algun dato asociado a la clave en el abb.
bool abb_pertenece(const abb_t *abb, const char *clave);

//post: devuelve la cantidad de datos guardados en el abb.
//devuelve cero si el abb no existe o si esta vacio.
size_t abb_cantidad(const abb_t *abb);

//post: libera la memoria ocupada por la estructura abb y los datos que esten 
//contenidos en él.
void abb_destruir(abb_t *abb);

//realiza un recorrido inorden del abb hasta llegar al final del mismo o 
//hasta que la funcion visitar devuelva false.
void abb_in_order(abb_t *abb, bool visitar(const char *, void *, void *), void *extra);

//post: devuelve un iterador posicionado en el primer dato de un recorrido inorden
//del abb. 
//devuelve NULL si el abb no existe o si no se pudo completar la operacion.
abb_iter_t *abb_iter_in_crear(const abb_t *abb);

//post: devuelve true si se logro relocalizar el iterador en una posicion valida
// y continua a la anterior en un recorrido inorden del abb.
bool abb_iter_in_avanzar(abb_iter_t *iter);

//post: devuelve la clave asociado al dato al sobre él cual esta posicionado el iterador.
//devuelve NULL si el iterador no existe o si el iterador esta localizado sobre 
//una posicion invalida.
const char *abb_iter_in_ver_actual(const abb_iter_t *iter);

//post: devuelve true si el iterador concluyo con su recorrido inorden por el abb.
bool abb_iter_in_al_final(const abb_iter_t *iter);

//post: se libera la memoria ocupada por la estructura abb_iter.
void abb_iter_in_destruir(abb_iter_t* iter);

#endif //ARBOL_H
